From dfb2a4c45c081796848416f706f50fcc4d4c1a20 Mon Sep 17 00:00:00 2001 From: tsteven4 Date: Thu, 30 Aug 2018 10:36:07 -0600 Subject: [PATCH] introduce optional class for things that may or may not have a value. demonstrate usage with computed_trkdata. --- defs.h | 37 +- gpssim.cc | 2 +- gtrnctr.cc | 35 +- kml.cc | 70 +- reference/earth-expertgps-track.kml | 1949 +++++++++-------- reference/earth-expertgps.kml | 1945 ++++++++-------- .../track/gpx_garmin_extensions-kml_track.kml | 233 +- reference/track/tracks~gpx.kml | 9 +- route.cc | 74 +- src/core/optional.h | 248 +++ 10 files changed, 2414 insertions(+), 2188 deletions(-) create mode 100644 src/core/optional.h diff --git a/defs.h b/defs.h index cbabfc1cc..2958bc15f 100644 --- a/defs.h +++ b/defs.h @@ -36,7 +36,8 @@ #include -# include "src/core/datetime.h" +#include "src/core/datetime.h" +#include "src/core/optional.h" #define CSTR(qstr) (qstr.toUtf8().constData()) #define CSTRc(qstr) (qstr.toLatin1().constData()) @@ -628,22 +629,22 @@ waypt_disp_all(T cb) } /* - * Structure of recomputed track/roue data. + * Structure of recomputed track/route data. */ -typedef struct { - double distance_meters; - double max_alt; /* unknown_alt => invalid */ - double min_alt; /* -unknown_alt => invalid */ - double max_spd; /* Meters/sec */ - double min_spd; /* Meters/sec */ - double avg_hrt; /* Avg Heartrate */ - double avg_cad; /* Avg Cadence */ - time_t start; /* Min time */ - time_t end; /* Max time */ - int min_hrt; /* Min Heartrate */ - int max_hrt; /* Max Heartrate */ - int max_cad; /* Max Cadence */ -} computed_trkdata; +struct computed_trkdata { + double distance_meters{0.0}; + gpsbabel_optional::optional max_alt; /* Meters */ + gpsbabel_optional::optional min_alt; /* Meters */ + gpsbabel_optional::optional max_spd; /* Meters/sec */ + gpsbabel_optional::optional min_spd; /* Meters/sec */ + gpsbabel_optional::optional avg_hrt; /* Avg Heartrate */ + gpsbabel_optional::optional avg_cad; /* Avg Cadence */ + gpsbabel::DateTime start; /* Min time */ + gpsbabel::DateTime end; /* Max time */ + gpsbabel_optional::optional min_hrt; /* Min Heartrate */ + gpsbabel_optional::optional max_hrt; /* Max Heartrate */ + gpsbabel_optional::optional max_cad; /* Max Cadence */ +}; class route_head { @@ -707,7 +708,7 @@ void route_backup(signed int* count, queue** head_bak); void route_restore(queue* head_bak); void track_backup(signed int* count, queue** head_bak); void track_restore(queue* head_bak); -void track_recompute(const route_head* trk, computed_trkdata**); +computed_trkdata track_recompute(const route_head* trk); template void @@ -1207,8 +1208,6 @@ int parse_distance(const char* str, double* val, double scale, const char* modul int parse_distance(const QString& str, double* val, double scale, const char* module); int parse_speed(const char* str, double* val, const double scale, const char* module); int parse_speed(const QString& str, double* val, const double scale, const char* module); -time_t parse_date(const char* str, const char* format, const char* module); -time_t parse_date(const QString& str, const char* format, const char* module); /* * From util_crc.c diff --git a/gpssim.cc b/gpssim.cc index 277f87c44..d5cd442ad 100644 --- a/gpssim.cc +++ b/gpssim.cc @@ -149,7 +149,7 @@ gpssim_trk_hdr(const route_head* rh) QString ofname = QString("%1%2%3.gpssim").arg(fnamestr).arg(doing_tracks ? "-track" : "-route").arg(trk_count++, 4, 10, QChar('0')); fout = gbfopen(ofname, "wb", MYNAME); } - track_recompute(rh, nullptr); + (void) track_recompute(rh); } static void diff --git a/gtrnctr.cc b/gtrnctr.cc index 264348370..fe317c757 100644 --- a/gtrnctr.cc +++ b/gtrnctr.cc @@ -35,7 +35,6 @@ static int lap_ct = 0; static int lap_s = 0; static Waypoint* wpt_tmp; static route_head* trk_head; -static computed_trkdata* tdata; #define MYNAME "gtc" @@ -255,10 +254,10 @@ gtc_lap_start(const route_head*) gtc_most_time = gpsbabel::DateTime(); } -static void +static computed_trkdata gtc_new_study_lap(const route_head* rte) { - track_recompute(rte, &tdata); /* called routine allocates space for tdata */ + return track_recompute(rte); } static void @@ -339,7 +338,7 @@ gtc_waypt_pr(const Waypoint* wpt) } static void -gtc_fake_hdr() +gtc_fake_hdr(const computed_trkdata& tdata) { /* handle the CourseLap_t or the ActivityLap_t types. */ /* note that the elements must appear in the order required by the schema. */ @@ -352,7 +351,7 @@ gtc_fake_hdr() /* write these in either case, course or activity format */ gtc_write_xml(0, "%d\n", secs); - gtc_write_xml(0, "%.2f\n", tdata->distance_meters); + gtc_write_xml(0, "%.2f\n", tdata.distance_meters); if (gtc_course_flag) { /* course format */ gtc_write_xml(1, "\n"); gtc_write_xml(0, "%lf\n", gtc_start_lat); @@ -364,24 +363,24 @@ gtc_fake_hdr() gtc_write_xml(-1,"\n"); } else { /* activity (history) format */ - if (tdata->max_spd) { - gtc_write_xml(0, "%.3f\n", tdata->max_spd); + if (tdata.max_spd) { + gtc_write_xml(0, "%.3f\n", *tdata.max_spd); } gtc_write_xml(0, "0\n"); /* element is required */ } - if (tdata->avg_hrt) { + if (tdata.avg_hrt) { gtc_write_xml(1, "\n"); - gtc_write_xml(0, "%d\n", (int)(tdata->avg_hrt + 0.5)); + gtc_write_xml(0, "%d\n", (int)(*tdata.avg_hrt + 0.5)); gtc_write_xml(-1,"\n"); } - if (tdata->max_hrt) { + if (tdata.max_hrt) { gtc_write_xml(1, "\n"); - gtc_write_xml(0, "%d\n", (int)(tdata->max_hrt + 0.5)); + gtc_write_xml(0, "%d\n", *tdata.max_hrt); gtc_write_xml(-1,"\n"); } gtc_write_xml(0, "Active\n"); - if (tdata->avg_cad) { - gtc_write_xml(0, "%d\n", tdata->avg_cad); + if (tdata.avg_cad) { + gtc_write_xml(0, "%d\n", (int)(*tdata.avg_cad + 0.5)); } if (!gtc_course_flag) { /* activity (history) format */ @@ -395,7 +394,7 @@ gtc_act_hdr(const route_head* rte) { gtc_write_xml(1, "\n", gtc_sportlist[gtc_sport]); gtc_lap_start(nullptr); - gtc_new_study_lap(rte); + computed_trkdata tdata = gtc_new_study_lap(rte); route_disp(rte, gtc_study_lap); if (gtc_least_time.isValid()) { gtc_write_xml(0, "%s\n", @@ -405,8 +404,7 @@ gtc_act_hdr(const route_head* rte) } else { gtc_write_xml(1, "\n"); } - gtc_fake_hdr(); - xfree(tdata); + gtc_fake_hdr(tdata); gtc_write_xml(1,"\n"); } @@ -424,7 +422,7 @@ gtc_crs_hdr(const route_head* rte) gtc_write_xml(1, "\n"); gtc_lap_start(nullptr); - gtc_new_study_lap(rte); + computed_trkdata tdata = gtc_new_study_lap(rte); route_disp(rte, gtc_study_lap); if (!rte->rte_name.isEmpty()) { @@ -435,9 +433,8 @@ gtc_crs_hdr(const route_head* rte) } /* write_optional_xml_entity(ofd, " ", "Name", rte->rte_name); */ gtc_write_xml(1, "\n"); - gtc_fake_hdr(); + gtc_fake_hdr(tdata); gtc_write_xml(-1, "\n"); - xfree(tdata); gtc_write_xml(1,"\n"); } diff --git a/kml.cc b/kml.cc index 2eed103d8..d0d1859ca 100644 --- a/kml.cc +++ b/kml.cc @@ -734,12 +734,8 @@ void kml_td(gpsbabel::XmlStreamWriter& hwriter, const QString& data) * Output the track summary. */ static -void kml_output_trkdescription(const route_head* header, computed_trkdata* td) +void kml_output_trkdescription(const route_head* header, const computed_trkdata* td) { - const char* max_alt_units; - const char* min_alt_units; - const char* distance_units; - if (!td || !trackdata) { return; } @@ -747,10 +743,6 @@ void kml_output_trkdescription(const route_head* header, computed_trkdata* td) QString hstring; gpsbabel::XmlStreamWriter hwriter(&hstring); - double max_alt = fmt_altitude(td->max_alt, &max_alt_units); - double min_alt = fmt_altitude(td->min_alt, &min_alt_units); - double distance = fmt_distance(td->distance_meters, &distance_units); - writer->writeEmptyElement(QStringLiteral("snippet")); writer->writeStartElement(QStringLiteral("description")); @@ -759,55 +751,55 @@ void kml_output_trkdescription(const route_head* header, computed_trkdata* td) if (!header->rte_desc.isEmpty()) { kml_td(hwriter, QStringLiteral("Description"), QStringLiteral(" %1 ").arg(header->rte_desc)); } + const char* distance_units; + double distance = fmt_distance(td->distance_meters, &distance_units); kml_td(hwriter, QStringLiteral("Distance"), QStringLiteral(" %1 %2 ").arg(QString::number(distance, 'f', 1)).arg(distance_units)); - if (td->min_alt != -unknown_alt) { + if (td->min_alt) { + const char* min_alt_units; + double min_alt = fmt_altitude(*td->min_alt, &min_alt_units); kml_td(hwriter, QStringLiteral("Min Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(min_alt, 'f', 3)).arg(min_alt_units)); } - if (td->max_alt != unknown_alt) { + if (td->max_alt) { + const char* max_alt_units; + double max_alt = fmt_altitude(*td->max_alt, &max_alt_units); kml_td(hwriter, QStringLiteral("Max Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(max_alt, 'f', 3)).arg(max_alt_units)); } if (td->min_spd) { const char* spd_units; - double spd = fmt_speed(td->min_spd, &spd_units); + double spd = fmt_speed(*td->min_spd, &spd_units); kml_td(hwriter, QStringLiteral("Min Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1)).arg(spd_units)); } if (td->max_spd) { const char* spd_units; - double spd = fmt_speed(td->max_spd, &spd_units); + double spd = fmt_speed(*td->max_spd, &spd_units); kml_td(hwriter, QStringLiteral("Max Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1)).arg(spd_units)); } - if (td->max_spd && td->start && td->end) { + if (td->max_spd && td->start.isValid() && td->end.isValid()) { const char* spd_units; - time_t elapsed = td->end - td->start; + double elapsed = td->start.msecsTo(td->end)/1000.0; double spd = fmt_speed(td->distance_meters / elapsed, &spd_units); if (spd > 1.0) { kml_td(hwriter, QStringLiteral("Avg Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1)).arg(spd_units)); } } if (td->avg_hrt) { - kml_td(hwriter, QStringLiteral("Avg Heart Rate"), QStringLiteral(" %1 bpm ").arg(QString::number(td->avg_hrt, 'f', 1))); + kml_td(hwriter, QStringLiteral("Avg Heart Rate"), QStringLiteral(" %1 bpm ").arg(QString::number(*td->avg_hrt, 'f', 1))); } - if (td->min_hrt < td->max_hrt) { - kml_td(hwriter, QStringLiteral("Min Heart Rate"), QStringLiteral(" %1 bpm ").arg(QString::number(td->min_hrt))); + if (td->min_hrt) { + kml_td(hwriter, QStringLiteral("Min Heart Rate"), QStringLiteral(" %1 bpm ").arg(QString::number(*td->min_hrt))); } if (td->max_hrt) { - kml_td(hwriter, QStringLiteral("Max Heart Rate"), QStringLiteral(" %1 bpm ").arg(QString::number(td->max_hrt))); + kml_td(hwriter, QStringLiteral("Max Heart Rate"), QStringLiteral(" %1 bpm ").arg(QString::number(*td->max_hrt))); } if (td->avg_cad) { - kml_td(hwriter, QStringLiteral("Avg Cadence"), QStringLiteral(" %1 rpm ").arg(QString::number(td->avg_cad, 'f', 1))); + kml_td(hwriter, QStringLiteral("Avg Cadence"), QStringLiteral(" %1 rpm ").arg(QString::number(*td->avg_cad, 'f', 1))); } if (td->max_cad) { - kml_td(hwriter, QStringLiteral("Max Cadence"), QStringLiteral(" %1 rpm ").arg(QString::number(td->max_cad))); + kml_td(hwriter, QStringLiteral("Max Cadence"), QStringLiteral(" %1 rpm ").arg(QString::number(*td->max_cad))); } - if (td->start && td->end) { - gpsbabel::DateTime t = QDateTime::fromTime_t(td->start); - if (t.isValid()) { - kml_td(hwriter, QStringLiteral("Start Time"), t.toPrettyString()); - } - t = QDateTime::fromTime_t(td->end); - if (t.isValid()) { - kml_td(hwriter, QStringLiteral("End Time"), t.toPrettyString()); - } + if (td->start.isValid() && td->end.isValid()) { + kml_td(hwriter, QStringLiteral("Start Time"), td->start.toPrettyString()); + kml_td(hwriter, QStringLiteral("End Time"), td->end.toPrettyString()); } hwriter.writeCharacters(QStringLiteral("\n")); @@ -819,21 +811,17 @@ void kml_output_trkdescription(const route_head* header, computed_trkdata* td) writer->writeEndElement(); // Close description tag /* We won't always have times. Garmin saved tracks, for example... */ - if (td->start && td->end) { + if (td->start.isValid() && td->end.isValid()) { writer->writeStartElement(QStringLiteral("TimeSpan")); - - gpsbabel::DateTime t = QDateTime::fromTime_t(td->start); - writer->writeTextElement(QStringLiteral("begin"), t.toPrettyString()); - t = QDateTime::fromTime_t(td->end); - writer->writeTextElement(QStringLiteral("end"), t.toPrettyString()); - + writer->writeTextElement(QStringLiteral("begin"), td->start.toPrettyString()); + writer->writeTextElement(QStringLiteral("end"), td->end.toPrettyString()); writer->writeEndElement(); // Close TimeSpan tag } } static -void kml_output_header(const route_head* header, computed_trkdata* td) +void kml_output_header(const route_head* header, const computed_trkdata* td) { if (!realtime_positioning) { writer->writeStartElement(QStringLiteral("Folder")); @@ -1652,12 +1640,10 @@ static void kml_waypt_pr(const Waypoint* waypointp) static void kml_track_hdr(const route_head* header) { - computed_trkdata* td; - track_recompute(header, &td); + computed_trkdata td = track_recompute(header); if (header->rte_waypt_ct > 0 && (export_lines || export_points)) { - kml_output_header(header, td); + kml_output_header(header, &td); } - xfree(td); } static void kml_track_disp(const Waypoint* waypointp) diff --git a/reference/earth-expertgps-track.kml b/reference/earth-expertgps-track.kml index f7ef4b1e6..207b78b3f 100644 --- a/reference/earth-expertgps-track.kml +++ b/reference/earth-expertgps-track.kml @@ -11,7 +11,7 @@ 36.257086 2979727.763965 - + - + - + - + - + - + - + - + - + - + - + - Heart Rate + Heart Rate - Cadence + Cadence @@ -184,20 +184,21 @@ - Distance 85.9 ft - Min Alt -51.588 ft - Max Alt 0.449 ft - Max Speed 11.3 mph - Avg Speed 8.4 mph - Avg Heart Rate 113.9 bpm - Min Heart Rate 111 bpm - Max Heart Rate 117 bpm - Avg Cadence 135.0 rpm - Max Cadence 153 rpm - Start Time 2008-08-20T07:04:48Z - End Time 2008-08-20T07:04:55Z - ]]> - +Distance 85.9 ft +Min Alt -51.588 ft +Max Alt 0.449 ft +Min Speed 2.7 mph +Max Speed 11.3 mph +Avg Speed 8.4 mph +Avg Heart Rate 113.9 bpm +Min Heart Rate 111 bpm +Max Heart Rate 117 bpm +Avg Cadence 135.0 rpm +Max Cadence 153 rpm +Start Time2008-08-20T07:04:48Z +End Time2008-08-20T07:04:55Z +]]> + 2008-08-20T07:04:48Z 2008-08-20T07:04:55Z @@ -208,16 +209,16 @@ 2008-08-20T07:04:47Z-0 - Longitude: -0.035187 - Latitude: 51.506172 - Altitude: 0.449 ft - Heart rate: 111 - Cadence: 151 - Heading: 360.0 - Time: 2008-08-20T07:04:48Z - - ]]> + + + + + + + + +
Longitude: -0.035187
Latitude: 51.506172
Altitude: 0.449 ft
Heart rate: 111
Cadence: 151
Heading: 360.0
Time: 2008-08-20T07:04:48Z
+]]> -0.035187 51.506172 @@ -235,17 +236,17 @@ 2008-08-20T07:04:47Z-1 - Longitude: -0.035242 - Latitude: 51.506196 - Altitude: -2.703 ft - Heart rate: 112 - Cadence: 153 - Speed: 10.4 mph - Heading: 305.0 - Time: 2008-08-20T07:04:49Z - - ]]> + + + + + + + + + +
Longitude: -0.035242
Latitude: 51.506196
Altitude: -2.703 ft
Heart rate: 112
Cadence: 153
Speed: 10.4 mph
Heading: 305.0
Time: 2008-08-20T07:04:49Z
+]]> -0.035242 51.506196 @@ -263,17 +264,17 @@ 2008-08-20T07:04:47Z-2 - Longitude: -0.035303 - Latitude: 51.506221 - Altitude: -51.588 ft - Heart rate: 113 - Cadence: 153 - Speed: 11.3 mph - Heading: 303.4 - Time: 2008-08-20T07:04:50Z - - ]]> + + + + + + + + + +
Longitude: -0.035303
Latitude: 51.506221
Altitude: -51.588 ft
Heart rate: 113
Cadence: 153
Speed: 11.3 mph
Heading: 303.4
Time: 2008-08-20T07:04:50Z
+]]> -0.035303 51.506221 @@ -291,17 +292,17 @@ 2008-08-20T07:04:47Z-3 - Longitude: -0.035354 - Latitude: 51.506246 - Altitude: -51.588 ft - Heart rate: 114 - Cadence: 153 - Speed: 10.1 mph - Heading: 308.2 - Time: 2008-08-20T07:04:51Z - - ]]> + + + + + + + + + +
Longitude: -0.035354
Latitude: 51.506246
Altitude: -51.588 ft
Heart rate: 114
Cadence: 153
Speed: 10.1 mph
Heading: 308.2
Time: 2008-08-20T07:04:51Z
+]]> -0.035354 51.506246 @@ -319,16 +320,16 @@ 2008-08-20T07:04:47Z-4 - Longitude: -0.035400 - Latitude: 51.506271 - Altitude: -50.013 ft - Heart rate: 114 - Speed: 9.5 mph - Heading: 311.1 - Time: 2008-08-20T07:04:52Z - - ]]> + + + + + + + + +
Longitude: -0.035400
Latitude: 51.506271
Altitude: -50.013 ft
Heart rate: 114
Speed: 9.5 mph
Heading: 311.1
Time: 2008-08-20T07:04:52Z
+]]> -0.035400 51.506271 @@ -346,16 +347,16 @@ 2008-08-20T07:04:47Z-5 - Longitude: -0.035438 - Latitude: 51.506297 - Altitude: -50.013 ft - Heart rate: 114 - Speed: 8.8 mph - Heading: 317.7 - Time: 2008-08-20T07:04:53Z - - ]]> + + + + + + + + +
Longitude: -0.035438
Latitude: 51.506297
Altitude: -50.013 ft
Heart rate: 114
Speed: 8.8 mph
Heading: 317.7
Time: 2008-08-20T07:04:53Z
+]]> -0.035438 51.506297 @@ -373,17 +374,17 @@ 2008-08-20T07:04:47Z-6 - Longitude: -0.035462 - Latitude: 51.506315 - Altitude: -50.013 ft - Heart rate: 116 - Cadence: 76 - Speed: 5.8 mph - Heading: 320.3 - Time: 2008-08-20T07:04:54Z - - ]]> + + + + + + + + + +
Longitude: -0.035462
Latitude: 51.506315
Altitude: -50.013 ft
Heart rate: 116
Cadence: 76
Speed: 5.8 mph
Heading: 320.3
Time: 2008-08-20T07:04:54Z
+]]> -0.035462 51.506315 @@ -401,17 +402,17 @@ 2008-08-20T07:04:47Z-7 - Longitude: -0.035472 - Latitude: 51.506324 - Altitude: -50.013 ft - Heart rate: 117 - Cadence: 124 - Speed: 2.7 mph - Heading: 325.3 - Time: 2008-08-20T07:04:55Z - - ]]> + + + + + + + + + +
Longitude: -0.035472
Latitude: 51.506324
Altitude: -50.013 ft
Heart rate: 117
Cadence: 124
Speed: 2.7 mph
Heading: 325.3
Time: 2008-08-20T07:04:55Z
+]]> -0.035472 51.506324 @@ -432,15 +433,15 @@ 1 - -0.035187,51.506172,0.14 - -0.035242,51.506196,-0.82 - -0.035303,51.506221,-15.72 - -0.035354,51.506246,-15.72 - -0.035400,51.506271,-15.24 - -0.035438,51.506297,-15.24 - -0.035462,51.506315,-15.24 - -0.035472,51.506324,-15.24 - +-0.035187,51.506172,0.14 +-0.035242,51.506196,-0.82 +-0.035303,51.506221,-15.72 +-0.035354,51.506246,-15.72 +-0.035400,51.506271,-15.24 +-0.035438,51.506297,-15.24 +-0.035462,51.506315,-15.24 +-0.035472,51.506324,-15.24 +
diff --git a/reference/track/tracks~gpx.kml b/reference/track/tracks~gpx.kml index 06439e228..0400a7e7e 100644 --- a/reference/track/tracks~gpx.kml +++ b/reference/track/tracks~gpx.kml @@ -784,15 +784,16 @@ Distance 7.7 km Min Alt 0.000 meters Max Alt 7.000 meters +Min Speed 361.3 meters/hour Max Speed 41.1 km/hour Avg Speed 3.8 km/hour -Start Time2002-05-25T17:06:21Z -End Time2002-05-25T19:05:57Z +Start Time2002-05-25T17:06:21.250Z +End Time2002-05-25T19:05:57.980Z ]]> - 2002-05-25T17:06:21Z - 2002-05-25T19:05:57Z + 2002-05-25T17:06:21.250Z + 2002-05-25T19:05:57.980Z Points diff --git a/route.cc b/route.cc index 5348795ed..af61a2d29 100644 --- a/route.cc +++ b/route.cc @@ -520,7 +520,7 @@ tracks_to_routes() * If trkdatap is non-null upon entry, a pointer to an allocated collection * (hopefully interesting) statistics about the track will be placed there. */ -void track_recompute(const route_head* trk, computed_trkdata** trkdatap) +computed_trkdata track_recompute(const route_head* trk) { Waypoint first; Waypoint* prev = &first; @@ -530,18 +530,11 @@ void track_recompute(const route_head* trk, computed_trkdata** trkdatap) double tot_hrt = 0.0; int pts_cad = 0; double tot_cad = 0.0; - computed_trkdata* tdata = (computed_trkdata*)xcalloc(1, sizeof(computed_trkdata)); - - if (trkdatap) { - *trkdatap = tdata; - } + computed_trkdata tdata; // first.latitude = 0; // first.longitude = 0; // first.creation_time = 0; - tdata->min_hrt = 9999; - tdata->min_alt = -unknown_alt; - tdata->max_alt = unknown_alt; QUEUE_FOR_EACH((queue*)&trk->waypoint_list, elem, tmp) { Waypoint* thisw = reinterpret_cast(elem); @@ -561,7 +554,7 @@ void track_recompute(const route_head* trk, computed_trkdata** trkdatap) * Avoid that 6300 mile jump as we move from 0,0. */ if (plat && plon) { - tdata->distance_meters += dist; + tdata.distance_meters += dist; } /* @@ -580,73 +573,72 @@ void track_recompute(const route_head* trk, computed_trkdata** trkdatap) } } if (WAYPT_HAS(thisw, speed)) { - if (thisw->speed > tdata->max_spd) { - tdata->max_spd = thisw->speed; + if ((!tdata.min_spd) || (thisw->speed < tdata.min_spd)) { + tdata.min_spd = thisw->speed; } - if (thisw->speed < tdata->min_spd) { - tdata->min_spd = thisw->speed; + if ((!tdata.max_spd) || (thisw->speed > tdata.max_spd)) { + tdata.max_spd = thisw->speed; } } if (thisw->altitude != unknown_alt) { - if (thisw->altitude < tdata->min_alt) { - tdata->min_alt = thisw->altitude; + if ((!tdata.min_alt) || (thisw->altitude < tdata.min_alt)) { + tdata.min_alt = thisw->altitude; } - if (thisw->altitude > tdata->max_alt) { - tdata->max_alt = thisw->altitude; + if ((!tdata.max_alt) || (thisw->altitude > tdata.max_alt)) { + tdata.max_alt = thisw->altitude; } } if (thisw->heartrate > 0) { pts_hrt++; - tot_hrt += (float) thisw->heartrate; - } - - if ((thisw->heartrate > 0) && (thisw->heartrate < tdata->min_hrt)) { - tdata->min_hrt = (int) thisw->heartrate; + tot_hrt += thisw->heartrate; } - if ((thisw->heartrate > 0) && (thisw->heartrate > tdata->max_hrt)) { - tdata->max_hrt = (int) thisw->heartrate; + if (thisw->heartrate > 0) { + if ((!tdata.min_hrt) || (thisw->heartrate < tdata.min_hrt)) { + tdata.min_hrt = thisw->heartrate; + } + if ((!tdata.max_hrt) || (thisw->heartrate > tdata.max_hrt)) { + tdata.max_hrt = thisw->heartrate; + } } if (thisw->cadence > 0) { pts_cad++; - tot_cad += (float) thisw->cadence; + tot_cad += thisw->cadence; } - if ((thisw->cadence > 0) && (thisw->cadence > tdata->max_cad)) { - tdata->max_cad = (int) thisw->cadence; + if ((thisw->cadence > 0) && ((!tdata.max_cad) || (thisw->cadence > tdata.max_cad))) { + tdata.max_cad = thisw->cadence; } - if (thisw->GetCreationTime().isValid() && (thisw->GetCreationTime().toTime_t() < tdata->start)) { - tdata->start = thisw->GetCreationTime().toTime_t(); - } + if (thisw->GetCreationTime().isValid()) { + if (!tdata.start.isValid() || (thisw->GetCreationTime() < tdata.start)) { + tdata.start = thisw->GetCreationTime(); + } - if (thisw->creation_time.toTime_t() > tdata->end) { - tdata->end = thisw->GetCreationTime().toTime_t(); - if (tdata->start == 0) { - tdata->start = tdata->end; + if (!tdata.end.isValid() || (thisw->GetCreationTime() > tdata.end)) { + tdata.end = thisw->GetCreationTime(); } } - prev = thisw; + if (thisw->shortname.isEmpty()) { thisw->shortname = QString("%1-%2").arg(trk->rte_name).arg(tkpt); } tkpt++; + prev = thisw; } if (pts_hrt > 0) { - tdata->avg_hrt = tot_hrt / (float) pts_hrt; + tdata.avg_hrt = tot_hrt / pts_hrt; } if (pts_cad > 0) { - tdata->avg_cad = tot_cad / (float) pts_cad; + tdata.avg_cad = tot_cad / pts_cad; } - if (!trkdatap) { - xfree(tdata); - } + return tdata; } route_head::route_head() : diff --git a/src/core/optional.h b/src/core/optional.h new file mode 100644 index 000000000..3ae4efb65 --- /dev/null +++ b/src/core/optional.h @@ -0,0 +1,248 @@ +/* + Copyright (C) 2018 Robert Lipe, robertlipe@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +// someday, when we require c++17, +// the intent is that this can all go away by +// changing: +// 1. 'gpsbabel_optional::optional' to 'std::optional', +// 2. 'include "optional.h"' becomes 'include '. + +#if __cplusplus >= 201703L +#warning "using std::optional" +#include +#define gpsbabel_optional std +#else +#include +namespace gpsbabel_optional +{ +template +class optional +{ +private: + bool null{true}; + T v{}; + +public: + constexpr optional() noexcept = default; + explicit optional(T n) : null{false}, v{n} {} + + // There is a known mismatch with std::optional. + // o = {}; should act like reset() so o.has_value() returns false. + // instead o.has_value() returns true and o.value() returns 0. + optional& operator=(const T& rhs) + { + null = false; + v = rhs; + return *this; + } + + // if constexpr will conflict with constexpr non-const version in c++11, ok in c++14. + // intentionally does not check to see if a value is contained, use value() for that. + const T& operator*() const& + { + return v; + } + + // if constexpr will conflict with constexpr const version in c++11, ok in c++14. + // intentionally does not check to see if a value is contained, use value() for that. + T& operator*()& + { + return v; + } + + constexpr explicit operator bool() const noexcept + { + return !null; + } + + constexpr bool has_value() const noexcept + { + return !null; + } + + // if constexpr will conflict with constexpr const version in c++11, ok in c++14. + // if constexpr cannot use assert. + T& value() & + { + assert(!null); + return v; + } + + // if constexpr will conflict with constexpr non-const version in c++11, ok in c++14. + // if constexpr cannot use assert. + const T& value() const& + { + assert(!null); + return v; + } + + void reset() noexcept + { + null = true; + } +}; + +template< class T, class U > +constexpr bool operator==(const optional& lhs, const optional& rhs) +{ + if (bool(lhs) != bool(rhs)) { + return false; + } + if (bool(lhs) == false) { + return true; + } + return *lhs == *rhs; +} + +template< class T, class U > +constexpr bool operator!=(const optional& lhs, const optional& rhs) +{ + if (bool(lhs) != bool(rhs)) { + return true; + } + if (bool(lhs) == false) { + return false; + } + return *lhs != *rhs; +} + +template< class T, class U > +constexpr bool operator<(const optional& lhs, const optional& rhs) +{ + if (!rhs) { + return false; + } + if (!lhs) { + return true; + } + return *lhs < *rhs; +} + +template< class T, class U > +constexpr bool operator>(const optional& lhs, const optional& rhs) +{ + if (!lhs) { + return false; + } + if (!rhs) { + return true; + } + return *lhs > *rhs; +} + +template< class T, class U > +constexpr bool operator<=(const optional& lhs, const optional& rhs) +{ + if (!lhs) { + return true; + } + if (!rhs) { + return false; + } + return *lhs <= *rhs; +} + +template< class T, class U > +constexpr bool operator>=(const optional& lhs, const optional& rhs) +{ + if (!rhs) { + return true; + } + if (!lhs) { + return false; + } + return *lhs >= *rhs; +} + + +template< class T, class U > +constexpr bool operator==(const optional& opt, const U& value) +{ + return bool(opt) ? (*opt == value) : false; +} + +template< class T, class U > +constexpr bool operator==(const T& value, const optional& opt) +{ + return bool(opt) ? (value == *opt) : false; +} + +template< class T, class U > +constexpr bool operator!=(const optional& opt, const U& value) +{ + return bool(opt) ? (*opt != value) : true; +} + +template< class T, class U > +constexpr bool operator!=(const T& value, const optional& opt) +{ + return bool(opt) ? (value != *opt) : true; +} + +template< class T, class U > +constexpr bool operator<(const optional& opt, const U& value) +{ + return bool(opt) ? (*opt < value) : true; +} + +template< class T, class U > +constexpr bool operator<(const T& value, const optional& opt) +{ + return bool(opt) ? (value < *opt) : false; +} + +template< class T, class U > +constexpr bool operator<=(const optional& opt, const U& value) +{ + return bool(opt) ? *opt <= value : true; +} + +template< class T, class U > +constexpr bool operator<=(const T& value, const optional& opt) +{ + return bool(opt) ? value <= *opt : false; +} + +template< class T, class U > +constexpr bool operator>(const optional& opt, const U& value) +{ + return bool(opt) ? (*opt > value) : false; +} + +template< class T, class U > +constexpr bool operator>(const T& value, const optional& opt) +{ + return bool(opt) ? (value > *opt) : true; +} + +template< class T, class U > +constexpr bool operator>=(const optional& opt, const U& value) +{ + return bool(opt) ? (*opt >= value) : false; +} + +template< class T, class U > +constexpr bool operator>=(const T& value, const optional& opt) +{ + return bool(opt) ? (value >= *opt) : true; +} + +} // namespace +#endif + -- 2.30.2